package com.gitee.webdav.kernel;

import cn.hutool.core.map.CaseInsensitiveMap;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ServiceLoaderUtil;
import com.gitee.webdav.HomeStarter;
import com.gitee.webdav.monitor.MonitorHandler;
import com.gitee.webdav.xml.Error;
import lombok.extern.slf4j.Slf4j;
import org.smartboot.http.common.enums.HttpMethodEnum;
import org.smartboot.http.common.enums.HttpStatus;
import org.smartboot.http.server.HttpRequest;
import org.smartboot.http.server.HttpResponse;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author hongda.li@hand-china.com
 */
@Slf4j
public class ResourceDispatcher extends ResourceReadonlyHandler {

    @Remark("系统监控页处理器")
    private final MonitorHandler monitorHandler;

    @Remark("请求映射表")
    private final Map<String, ResourceReadonlyHandler> readonlyMap;

    public ResourceDispatcher() {
        this.monitorHandler = new MonitorHandler();
        List<ResourceReadonlyHandler> handlerList = ServiceLoaderUtil.loadList(ResourceReadonlyHandler.class);
        readonlyMap = new CaseInsensitiveMap<>(handlerList.size());
        for (ResourceReadonlyHandler handler : handlerList) {
            String name = handler.method().name();
            log.debug("注册资源处理器 : {} - {}", name, handler.getClass().getName());
            readonlyMap.put(name, handler);
        }
    }

    @Override
    public void handle(HttpRequest request, HttpResponse response) throws Throwable {
        try {
            String method = request.getMethod();
            log.debug("请求信息 : {} - {}", method, request.getRequestURI());

            if (this.matchSystemRequest(request, response)) {
                return;
            }

            ResourceReadonlyHandler readonly = readonlyMap.get(method);
            if (readonly == null) {
                log.warn("暂不支持的请求方法 : {}", method);
                response.setHttpStatus(HttpStatus.METHOD_NOT_ALLOWED);
                writeXml(response, Error.of(method));
                return;
            }

            readonly.handle(request, response);
        } catch (Exception e) {
            log.error("服务内部异常 : {}", e.getMessage());
            log.error("", e);
            response.setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR);
            writeXml(response, Error.of(e.getMessage()));
        }
    }

    private boolean matchSystemRequest(HttpRequest request, HttpResponse response) throws Throwable {
        String method = request.getMethod();
        String path = request.getRequestURI();
        if ((Objects.equals(path, HomeStarter.getRootPath()) && HttpMethodEnum.GET.getMethod().equals(method)) || HttpMethodEnum.POST.getMethod().equals(method)) {
            this.monitorHandler.handle(request, response);
            return true;
        } else {
            return false;
        }
    }

    @Override
    protected MethodEnum method() {
        throw new UnsupportedOperationException();
    }
}
